package com.ganzalang.gmall.common.utils;

import org.springframework.cglib.beans.BeanCopier;
import org.springframework.cglib.core.Converter;

import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.Map;

/**
 * @description:
 * @author: Ganzalang
 * @Date 2021/3/13 11:11
 */
public class BeanCopierUtils {
    public static Map<String, BeanCopier> beanCopierCacheMap = new HashMap();

    public BeanCopierUtils() {
    }

    public static void copyProperties(Object source, Object target) {
        String cacheKey = source.getClass().toString() + target.getClass().toString();
        BeanCopier beanCopier = null;
        if (!beanCopierCacheMap.containsKey(cacheKey)) {
            Class var4 = BeanCopierUtils.class;
            synchronized(BeanCopierUtils.class) {
                if (!beanCopierCacheMap.containsKey(cacheKey)) {
                    beanCopier = BeanCopier.create(source.getClass(), target.getClass(), false);
                    beanCopierCacheMap.put(cacheKey, beanCopier);
                } else {
                    beanCopier = (BeanCopier)beanCopierCacheMap.get(cacheKey);
                }
            }
        } else {
            beanCopier = (BeanCopier)beanCopierCacheMap.get(cacheKey);
        }

        beanCopier.copy(source, target, (Converter)null);
    }

    private static Object deepCopyConverter(Object bean) {
        if (bean == null) {
            return null;
        } else if (bean.getClass().isArray() && !bean.getClass().getComponentType().equals(Byte.TYPE)) {
            int length = Array.getLength(bean);
            Object clone = Array.newInstance(bean.getClass().getComponentType(), length);

            for(int i = 0; i < length; ++i) {
                Array.set(clone, i, deepCopyConverter(Array.get(bean, i)));
            }

            return clone;
        } else {
            return bean;
        }
    }

    public static <T> T clone(Object source, Class<T> target) {
        Object targetInstance = null;

        try {
            targetInstance = target.newInstance();
        } catch (Exception var4) {
            var4.printStackTrace();
        }

        copyProperties(source, targetInstance);
        return (T) targetInstance;
    }
}
